Skip to content

fix: derive call-workflow job permissions from caller, not worker (#40169)#40175

Merged
dsyme merged 8 commits into
mainfrom
fix/call-workflow-caller-permissions-40169
Jun 21, 2026
Merged

fix: derive call-workflow job permissions from caller, not worker (#40169)#40175
dsyme merged 8 commits into
mainfrom
fix/call-workflow-caller-permissions-40169

Conversation

@dsyme

@dsyme dsyme commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes a bug where buildCallWorkflowJobs was deriving the permission envelope of a generated call-workflow job from the worker's resolved permissions rather than the caller's declared permissions. This could cause generated workflows to run with an inflated or incorrect permission set that did not match what the caller author intended.

Problem

When a call-workflow job is compiled, the compiler previously set callJob.Permissions to the union of the worker's job-level permissions (rendered). The worker's permissions are derived dynamically and represent what the worker needs, not what the caller has explicitly declared. This violated the principle that a caller should never be granted permissions it did not ask for.

Changes

pkg/workflow/compiler_safe_output_jobs.go (high impact)

  • Removed the unconditional callJob.Permissions = rendered assignment that propagated worker permissions onto the generated job.
  • Added two new outcomes in its place:
    1. A non-fatal skip when the worker file is not yet resolved (e.g., in a batch where order matters).
    2. A missing-permission warning (non-fatal) surfaced via formatCompilerMessage + os.Stderr + c.IncrementWarningCount() when the caller's declared permissions do not fully cover the scopes the worker requires.
  • The call-worker job's permission envelope is now sourced exclusively from the caller's own declared Permissions field.

pkg/workflow/call_workflow_permissions.go (high impact)

  • Added permissionLevelRank helper to compare permission levels by severity order.
  • Added findUncoveredWorkerPermissions helper that returns the set of worker-required scopes not covered (at sufficient level) by the caller's declared permissions.
  • Fixed a missing worker.Get(scope) call inside findUncoveredWorkerPermissions (commit e34e404c1).
  • Clarified extractCallWorkflowPermissions doc comment: the function is used only for validation, never to inflate caller permissions.

pkg/workflow/call_workflow_permissions_test.go (medium impact)

  • Added TestFindUncoveredWorkerPermissions with six sub-cases covering:
    • fully-covered permissions (expect no warnings)
    • partially-covered and uncovered scopes
    • level-rank boundary cases (e.g., read vs write)
  • Revised existing end-to-end and YAML-output tests to assert that generated call-workflow jobs carry the caller's declared permissions, not the worker's.

pkg/cli/workflows/test-copilot-call-workflow.md (low impact)

  • Added issues: read and pull-requests: read to the test workflow's top-level permissions block to align the fixture with the new validation logic.

Behaviour Change

Scenario Before After
Caller declares contents: read; worker needs contents: write Job silently gets contents: write Job gets contents: read; compiler emits a warning that contents: write is uncovered
Caller declares all required scopes Job gets worker-derived permissions Job gets caller's declared permissions (same result in practice)
Worker file not yet resolved in batch Crash / wrong permissions Non-fatal skip; job is not emitted for this compile pass

Risk & Compatibility

  • Breaking: No — no public API, CLI flag, or config key is renamed or removed.
  • Compiler output: Permission envelopes on generated call-workflow jobs will now differ from previous output when the caller did not explicitly declare the worker's required scopes. This is a correctness fix.
  • Warnings: Projects where callers under-declare permissions will now see compiler warnings. These are non-fatal; the workflow is still emitted.

Generated by PR Description Updater for issue #40175 · 119.3 AIC · ⌖ 7.6 AIC · ⊞ 4.5K ·

…0169)

buildCallWorkflowJobs previously reverse-engineered the call-<worker>
job's permissions block from the union of the worker's job-level
permissions. When a worker job declared read-all, Merge() expanded it
across GetAllPermissionScopes(), materialising vulnerability-alerts:
read into the caller's lockfile. GitHub Actions rejects that scope on
GITHUB_TOKEN, causing startup_failure on every run.

The call-<worker> job now derives its permissions block from the
caller's own declared permissions. extractCallWorkflowPermissions
becomes a validation-only step: findUncoveredWorkerPermissions compares
the caller's declared permissions against the worker's requirements and
emits a compiler warning when the caller is insufficient, without ever
modifying the compiled permissions.

- pkg/workflow/compiler_safe_output_jobs.go: use caller's permissions,
  validate worker coverage, warn on gaps
- pkg/workflow/call_workflow_permissions.go: add permissionLevelRank and
  findUncoveredWorkerPermissions helpers; document validation-only role
- pkg/cli/workflows/test-copilot-call-workflow.md: widen caller perms to
  cover its worker under the new model
- regenerated affected lock files
Copilot AI review requested due to automatic review settings June 19, 2026 00:39
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Comment Memory

CI lights the path
Green checks bloom at dawn
Quiet bots still sing

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

Generated by 🧪 Smoke CI for issue #40175 ·

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The new worker-coverage validator misses the valid copilot-requests permission scope, which can prevent warnings for real permission gaps and lead to runtime failures.

Pull request overview

This PR fixes a safe-outputs call-workflow compilation design flaw by ensuring the generated call-<worker> job permissions are derived from the caller workflow’s declared permissions, rather than being inflated from the worker’s job permissions. It also adds validation that compares caller vs worker requirements and emits warnings when the caller’s permissions may be insufficient—without mutating the compiled permissions.

Changes:

  • Derive call-<worker> job permissions: from the caller’s declared permissions, and validate worker coverage via warnings rather than propagating worker permissions.
  • Add permission-level comparison helpers and a new unit test for uncovered worker permissions.
  • Update the test workflow’s declared permissions and regenerate affected lock files to reflect the caller-derived model.
File summaries
File Description
pkg/workflow/compiler_safe_output_jobs.go Switches call-workflow job permissions to be derived from caller permissions and adds warning-only validation against worker permissions.
pkg/workflow/call_workflow_permissions.go Adds permission ranking and uncovered-scope detection helper for validation-only comparison.
pkg/workflow/call_workflow_permissions_test.go Updates existing tests to assert caller-derived permissions and adds coverage for uncovered-scope detection.
pkg/cli/workflows/test-copilot-call-workflow.md Expands declared permissions so the caller covers its worker under the new model.
.github/workflows/smoke-call-workflow.lock.yml Regenerated to reflect caller-derived call-job permissions.
.github/workflows/dependabot-campaign.lock.yml Regenerated to reflect caller-derived call-job permissions.

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 1

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/workflow/call_workflow_permissions.go
The stored frontmatter_hash/body_hash in the lock file no longer matched
the values computed by the current hash logic, causing
TestHashConsistencyAcrossLockFiles to fail. Recompiling regenerates the
hash metadata; the generated workflow body is byte-identical (only the
gh-aw-metadata comment changes).
@github-actions

Copy link
Copy Markdown
Contributor

Generated by 👨‍🍳 PR Sous Chef · 42 AIC · ⌖ 1.36 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

``
@copilot review all comments and address unresolved review feedback.
Please fix the failing CGO test and then reply with the remaining blocker summary.

Generated by 👨‍🍳 PR Sous Chef · 42 AIC · ⌖ 1.36 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

@copilot review all comments and address unresolved review feedback.
Fix the uncovered copilot-requests permission warning, then rerun checks.

Generated by 👨‍🍳 PR Sous Chef · 58.3 AIC · ⌖ 0.958 AIC · ⊞ 17.2K ·

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

@copilot review all comments and address unresolved review feedback.

Please land the remaining fix and summarize any blockers.

Generated by 👨‍🍳 PR Sous Chef · 57 AIC · ⌖ 1.09 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

Please fix the copilot-requests warning and rerun checks.

Generated by 👨‍🍳 PR Sous Chef · 57 AIC · ⌖ 1.09 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

Please fix the copilot-requests warning and rerun checks.

Generated by 👨‍🍳 PR Sous Chef · 18.8 AIC · ⌖ 1.01 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

``
Please refresh the branch, rerun checks, and post the remaining blocker summary.

Generated by 👨‍🍳 PR Sous Chef · 53 AIC · ⌖ 1.09 AIC · ⊞ 17.3K ·

@github-actions

Copy link
Copy Markdown
Contributor

``
@copilot review all comments and address unresolved review feedback.
Please resolve the blocking review items and summarize the fix plan.

Generated by 👨‍🍳 PR Sous Chef · 53 AIC · ⌖ 1.09 AIC · ⊞ 17.3K ·

@dsyme

dsyme commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator Author

@copilot fix the CI errors

@github-actions

Copy link
Copy Markdown
Contributor

@copilot review all comments and address unresolved review feedback.

Generated by 👨‍🍳 PR Sous Chef · 93.3 AIC · ⌖ 1.86 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

@copilot summarize the remaining CI failures and propose the smallest fix.

Generated by 👨‍🍳 PR Sous Chef · 93.3 AIC · ⌖ 1.86 AIC · ⊞ 17.2K ·

…ions

Co-authored-by: dsyme <7204669+dsyme@users.noreply.github.com>

Copilot AI commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

@copilot fix the CI errors

Fixed in 3a7cebc. The CI failure was a build error in findUncoveredWorkerPermissions — the workerLevel, workerWants := worker.Get(scope) assignment was accidentally dropped when adding the PermissionCopilotRequests scope to the iteration. The loop now correctly calls worker.Get(scope) for every scope including copilot-requests.

Copilot finished work on behalf of dsyme June 19, 2026 20:35
@github-actions

Copy link
Copy Markdown
Contributor

@copilot review all comments and address unresolved review feedback.

Generated by 👨‍🍳 PR Sous Chef · 41.5 AIC · ⌖ 1.12 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

Please re-review now that the CI fix is pushed and summarize any remaining blockers.

Generated by 👨‍🍳 PR Sous Chef · 41.5 AIC · ⌖ 1.12 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

@copilot review all comments and address unresolved review feedback.
Please summarize any remaining blockers and next steps.

Generated by 👨‍🍳 PR Sous Chef · 49.1 AIC · ⌖ 1.09 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

@copilot please request a fresh review so maintainers can re-evaluate the branch.

Generated by 👨‍🍳 PR Sous Chef · 38.5 AIC · ⌖ 1.02 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

``
@copilot review all comments and address the unresolved review feedback on this PR.

Generated by 👨‍🍳 PR Sous Chef · 42.1 AIC · ⌖ 1.03 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

``
Please summarize the remaining blockers and rerun the failing checks after the review fixes land.

Generated by 👨‍🍳 PR Sous Chef · 42.1 AIC · ⌖ 1.03 AIC · ⊞ 17.2K ·

@github-actions

Copy link
Copy Markdown
Contributor

``

@copilot review all comments and address the unresolved review feedback on this PR.

Generated by 👨‍🍳 PR Sous Chef · 49.9 AIC · ⌖ 1.09 AIC · ⊞ 17.3K ·

@github-actions

Copy link
Copy Markdown
Contributor

Please address the Copilot review note about the missing copilot-requests scope.

Generated by 👨‍🍳 PR Sous Chef · 56.7 AIC · ⌖ 1.01 AIC · ⊞ 17.3K ·

@dsyme dsyme merged commit 11621eb into main Jun 21, 2026
29 checks passed
@dsyme dsyme deleted the fix/call-workflow-caller-permissions-40169 branch June 21, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants